﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Drawing;
using System.Collections;
using eeenno.ReaderEngine.Utilities;

namespace eeenno.ReaderEngine.Adapters
{
    public class WebManager
    {
        public static string SR_ERROR = "SR_ERROR";
        public static string SR_OFFLINE = "SR_OFFLINE";
        private static string _BIT_LY_API_KEY = "R_7ae19c5b518951c362772b7f65b999d3";
        private static string _BIT_LY_USERNAME = "eeenno";
        private static long _bytes_transferred = 0; 

        public static long bytes_transferred
        {
            get { return WebManager._bytes_transferred; }
            set { WebManager._bytes_transferred = value; }
        }

        public static bool IsRoaming()
        {
            return Microsoft.WindowsMobile.Status.SystemState.PhoneRoaming;
        }

        /// <summary>
        /// Returns whether the device has an open connection or possibility for an open connection
        /// </summary>
        /// <returns>Connection status</returns>
        public static bool IsConnected()
        {
            //check to see if their are any connections ie. wifi, activesync, cellular
            //
            if (Microsoft.WindowsMobile.Status.SystemState.ConnectionsCount == 0)
            {
                //there are no ACTIVE connections, check for cellular coverage
                if (Microsoft.WindowsMobile.Status.SystemState.PhoneNoService)
                {
                    return false; //no cellular coverage present
                }
                else //cellular coverage present
                {
                    return true;
                }
            }             
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Returns an http webrequest of method type POST or GET
        /// </summary>
        /// <param name="url"></param>
        /// <param name="isPost">True, if you want a POST http request, false if you want a GET request</param>
        /// <returns>Returns a httpwebrequest if in online mode, returns if not</returns>
        public static HttpWebRequest GetWebRequest(string url, bool isPost)
        {
            HttpWebRequest ret_val = null;
            if (!Settings.offline_mode_enabled)
            {
                ret_val = (HttpWebRequest)WebRequest.Create(new Uri(url));
                ret_val.Timeout = 30000;
                ret_val.Proxy = GlobalProxySelection.GetEmptyWebProxy();
                ret_val.UserAgent = "SpeeedReader/" + SpeeedReader.MajorVersion();
                if (isPost)
                {
                    ret_val.Method = "POST";
                }
                else
                {
                    ret_val.Method = "GET";
                }
                ret_val.AutomaticDecompression = DecompressionMethods.GZip;
                ret_val.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
            }
            return ret_val;
        }

        /// <summary>
        /// Returns an http webrequest of method type POST or GET
        /// </summary>
        /// <param name="url"></param>
        /// <param name="isPost">True, if you want a POST http request, false if you want a GET request</param>
        /// <param name="sid"></param>
        /// <param name="token"></param>
        /// <returns>Returns a httpwebrequest if in online mode, returns if not</returns>
        public static HttpWebRequest GetWebRequest(string url, bool isPost, string sid, string token, string auth)
        {
            HttpWebRequest ret_val = null;
            if (!Settings.offline_mode_enabled)
            {
                ret_val = GetWebRequest(url, isPost);
                ret_val.Headers.Add("Cookie", "SID=" + sid + ";T=" + token);
                ret_val.Headers.Add("Authorization","GoogleLogin auth=" + auth);
            }
            return ret_val;
        }

        public static bool DownloadFile(HttpWebRequest request, string file_name)
        {
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (FileStream fs = new FileStream(file_name, FileMode.Create))
                        {
                            byte[] read = new byte[256];
                            int count = stream.Read(read, 0, read.Length);
                            while (count > 0)
                            {
                                fs.Write(read, 0, count);
                                count = stream.Read(read, 0, read.Length);
                            }
                        }                     
                    }
                }
            }
            catch (WebException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message + " " + e.Status);
                return false;
            }
            catch (IOException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return false;
            }
            catch (OutOfMemoryException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return false;
            }
            catch (Exception e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return false;
            }
            
            return true;
        }
        

        public static string GetResponseStreamData(HttpWebRequest request)
        {
            string ret_val = String.Empty;
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8))
                        {
                            //disables data usage if (a) roaming and data while roaming is NOT enabled
                            //or the application is in offline mode
                            if ((IsRoaming() && !Settings.data_while_roaming_enabled) || Settings.offline_mode_enabled || !IsConnected())
                            {
                                ret_val = SR_OFFLINE;
                            }
                            else
                            {
                                if (response.StatusCode == HttpStatusCode.OK)
                                {
                                    ret_val = sr.ReadToEnd();
                                    _bytes_transferred += ret_val.Length;
                                }
                                else
                                {
                                    return SR_ERROR;
                                }
                            }
                        }
                    }
                }
            }
            catch (WebException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message + " " + e.Status);
                return SR_ERROR;
            }
            catch (IOException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return SR_ERROR;
            }
            catch (OutOfMemoryException e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return SR_ERROR;
            }
            catch (Exception e)
            {
                LogManager.LogError("WebManager.GetResponseStreamData", e.Message);
                return SR_ERROR;
            }
            
            return ret_val;
        }        

        /// <summary>
        /// Turns a URL into a Tiny URL
        /// </summary>
        /// <param name="url">URL to make tiny</param>
        /// <returns></returns>
        public static string ShortenUrl(string url)
        {
            string ret_val = url;
            HttpWebRequest url_request = null;

            if (Settings.shorten_url)
            {
                ret_val = "http://api.bit.ly/shorten?version=2.0.1&format=xml&longUrl=";
                ret_val += url + "&login=" + _BIT_LY_USERNAME + "&apiKey=" + _BIT_LY_API_KEY;
                url_request = WebManager.GetWebRequest(ret_val, false);
                if (url_request != null)
                {
                    ret_val = XmlEngine.ProcessShortenenedUrl(WebManager.GetResponseStreamData(url_request));
                }
            }
            return ret_val;
        }

        public static Bitmap GetBitmap(Icon icon)
        {
            Bitmap bmp = new Bitmap(icon.Width, icon.Height);
            //Create temporary graphics
            Graphics gxMem = Graphics.FromImage(bmp);
            //Draw the icon
            gxMem.DrawIcon(icon, 0, 0);
            //Clean up
            gxMem.Dispose();

            //The scaled bitmap
            Bitmap scaledBmp = new Bitmap(bmp.Width * 2, bmp.Height * 2);

            //Draw the source image to graphics object of the scaled image
            using (Graphics g = Graphics.FromImage(scaledBmp))
            {
                g.DrawImage(bmp,
                    new Rectangle(0, 0, scaledBmp.Width, scaledBmp.Height),
                    new Rectangle(0, 0, bmp.Width, bmp.Height),
                    GraphicsUnit.Pixel);
            }

            return scaledBmp;
        }

        public static byte[] GetFavicon(string base_url)
        {
            byte[] ret_val = null;
            Bitmap icon = null;
            HttpWebRequest favicon_request = null;

            if (base_url.Length > 0)
            {
                favicon_request = GetWebRequest(base_url + "/favicon.ico", false);
                try
                {
                    using (WebResponse favicon_response = favicon_request.GetResponse())
                    {
                        using (Stream s = favicon_response.GetResponseStream())
                        {
                            string content_encoding = favicon_response.Headers.Get("Content-Encoding");
                            if (content_encoding != null)
                            {
                                if (string.Compare(content_encoding, "gzip", true) == 0)
                                {
                                    using (GZipStream zip_stream = new GZipStream(s, CompressionMode.Decompress))
                                    {
                                        Bitmap bitmap = new Bitmap(s);
                                        using (MemoryStream stream = new MemoryStream())
                                        {
                                            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
                                            ret_val = stream.ToArray();
                                        }
                                    }
                                }
                            }
                            else
                            {
                                Bitmap bitmap = new Bitmap(s);
                                //icon = GetBitmap(new Icon(s));
                                using (MemoryStream stream = new MemoryStream())
                                {
                                    bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
                                    ret_val = stream.ToArray();
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                }
            }
            return ret_val;
        }
    }
}
